package com.artevivo.dao;

import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.hibernate.Criteria;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.criterion.MatchMode;
import org.hibernate.criterion.Order;
import org.hibernate.criterion.Projections;
import org.hibernate.criterion.Restrictions;
import org.primefaces.model.SortOrder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import com.artevivo.entidades.Cliente;
import com.artevivo.entidades.Matricula;
import com.artevivo.utilidades.Utilidades;

@Repository
public class ClienteDAO extends AbstractDAO<Cliente, Long> {

    public ClienteDAO() {
        super();
    }

    @Autowired
    public ClienteDAO(SessionFactory sessionFactory) {
        super(sessionFactory);
    }

    @Transactional
    public List<Cliente> findClienteByApellidosNombre(String apellidos, String nombre) {

        Session sesion = this.getSessionFactory().getCurrentSession();
        Criteria criteria = sesion.createCriteria(Cliente.class);
        criteria.add(Restrictions.eq("apellidos", apellidos));
        criteria.add(Restrictions.eq("nombre", nombre));
        List<Cliente> any = criteria.list();
        return any;
    }

    @Transactional
    public Cliente findClienteByDNI(String dni) {

        Session sesion = this.getSessionFactory().getCurrentSession();
        Cliente res = null;
        Criteria criteria = sesion.createCriteria(Cliente.class);
        criteria.add(Restrictions.eq("dni", dni));
        List<Cliente> any = criteria.list();
        if (any != null && !(any.isEmpty())) {
            res = any.get(0);
        }
        return res;
    }

    @Transactional(propagation = Propagation.REQUIRED)
    public List<Matricula> lazyLoad(int index, int count, String sortField, SortOrder sortOrder, Map<String, Object> filters) {
        Session s = this.getSessionFactory().getCurrentSession();

        Criteria crit = s.createCriteria(Matricula.class, "matricula").createAlias("matricula.cliente", "cliente");

        if (sortField != null && !sortField.isEmpty()) {
            if (sortOrder.equals(SortOrder.ASCENDING)) {
                crit = crit.addOrder(Order.asc(sortField));
            } else {
                crit = crit.addOrder(Order.desc(sortField));
            }
        }

        if (!filters.isEmpty()) {
            Iterator<Entry<String, Object>> iterator = filters.entrySet().iterator();
            while (iterator.hasNext()) {
                Entry<String, Object> entry = iterator.next();
                if (entry.getKey().equals("anyo")) {
                    crit = crit.add(Restrictions.eq(entry.getKey(), entry.getValue()));
                } else if (entry.getKey().equals("cliente.idCliente")) {
                    crit = crit.add(Restrictions.like(entry.getKey(), new Long(entry.getValue().toString())));
                } else if (entry.getKey().equals("cliente.dni")) {
                    crit = crit.add(Restrictions.like(entry.getKey(), Utilidades.formatearDni(entry.getValue().toString()), MatchMode.START));
                } else {
                    crit = crit.add(Restrictions.like(entry.getKey(),
                            Utilidades.convertirPrimeraMayusculaRestoMinusculas(entry.getValue().toString()), MatchMode.START));
                }
            }
        }

        crit = crit.setFirstResult(index).setMaxResults(count);

        List<Matricula> result = crit.list();

        return result;
    }

    @Transactional(propagation = Propagation.REQUIRED)
    public Long getClienteCount() {
        Session s = this.getSessionFactory().getCurrentSession();

        Criteria crit = s.createCriteria(Cliente.class).setProjection(Projections.rowCount());

        return (Long) crit.list().get(0);
    }
}
